package Common;

import POJO.*;
import PostLink.PostTest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.junit.Test;

import java.io.*;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class XMLUtils {


    @Test
    public void test1() throws Exception {
        readJSON();

    }

    //多线程 要多少改下面参数就行，不能超过5个
    @Test
    public void test2() throws Exception {

        multiThread(2);

    }

    public static void readJSON() throws Exception {
        FilePathMes.THREAD_NUM = 1;
        singleThread();
    }

    //单线程
    public static void singleThread() {
        try {
            // 读取以JSON结尾的文件，返回XML
            List<File> jsonFiles = JXFileUtils.findJxFiles(new File(FilePathMes.JSON_PATH), "json");
            if (jsonFiles.isEmpty()) throw new Exception("无法找到json场景文件");
            List<SelectResult> selectResults = new ArrayList<>();
            int num = 0;
            int error = 0;
            for (File file : jsonFiles) {
                error = 0;
                num++;
                // 先用一个固定的文档做测试
                String jsonContent = new String(DecryptUtil.readContent(file.getAbsolutePath()), "GBK");
                jsonContent = JXFileUtils.getSplitStr(jsonContent, "}") + "}";
                JSONObject jsonObject = (JSONObject) JSON.parse(jsonContent);
                JSONArray paramcabinet = jsonObject.getJSONArray("paramcabinet");

                FilePathMes.FILE_NAME = file.getName();
                for (Object p : paramcabinet) {

                    JSONObject js = (JSONObject) p;
                    TKUtils.data = js.getString("xml").replaceAll("encoding=\"ANSI\"", "encoding=\"UTF-8\"");
                    // XML字符串传入下一步,XML转为JSON
                    XmlMapper xmlMapper = new XmlMapper();
                    JsonNode jsonNode = xmlMapper.readTree(TKUtils.data.getBytes());

                    ObjectMapper objectMapper = new ObjectMapper();

                    TKUtils.data = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
                    // 测试数据
                    //byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\11040162\\IdeaProjects\\screening-script\\src\\main\\resources\\JSONData.txt"));
                    //TKUtils.data = new String(bytes, StandardCharsets.UTF_8);
                    // 将转换之后的JSON，处理成规则引擎需要处理的JSON
                    error = handleJSON(selectResults, new TKUtil());
                    if (error == 1) {
                        break;
                    }
                }
                System.out.println("已处理" + num + "/" + jsonFiles.size());
            }
            // 处理完一个文件下的筛单，把当前结果存储到Excel
            RuleMesgJSON.exportToExcel(selectResults, FilePathMes.JX_PATH + "\\" + TKUtils.TK_Number + ".xlsx");
            selectResults.clear();

        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println(TKUtils.data);
        }
    }

    //多线程处理
    public static void multiThread(int thread) throws Exception {
        // 1. 获取JSON文件列表
        FilePathMes.THREAD_NUM = thread;
        List<File> jsonFiles = JXFileUtils.findJxFiles(new File(FilePathMes.JSON_PATH), "json");
        if (jsonFiles.isEmpty()) {
            throw new Exception("无法找到json场景文件");
        }

        // 2. 创建线程安全的结果集合
        List<SelectResult> selectResults = new java.util.concurrent.CopyOnWriteArrayList<>();

        // 3. 创建固定2个线程的线程池
        ExecutorService executor = Executors.newFixedThreadPool(thread);
        AtomicInteger num = new AtomicInteger();
        // 4. 为每个文件创建处理任务并提交到线程池
        for (File file : jsonFiles) {

            // 提交任务到线程池
            Future<?> future = executor.submit(() -> {

                try {
                    // 处理单个文件的逻辑
                    String jsonContent = new String(DecryptUtil.readContent(file.getAbsolutePath()), "GBK");
                    jsonContent = JXFileUtils.getSplitStr(jsonContent, "}") + "}";
                    JSONObject jsonObject = (JSONObject) JSON.parse(jsonContent);
                    JSONArray paramcabinet = jsonObject.getJSONArray("paramcabinet");
                    TKUtil tkUtil = new TKUtil();
                    int error = 0;

                    String fileName = file.getName();
                    FilePathMes.FILE_NAME = fileName;
                    tkUtil.TK_Number = fileName;
                    for (Object p : paramcabinet) {
                        JSONObject js = (JSONObject) p;
                        String xmlData = js.getString("xml").replaceAll("encoding=\"ANSI\"", "encoding=\"UTF-8\"");
                        TKUtils.data = xmlData;
                        tkUtil.data = xmlData;


                        // XML转JSON
                        XmlMapper xmlMapper = new XmlMapper();
                        JsonNode jsonNode = xmlMapper.readTree(xmlData.getBytes(StandardCharsets.UTF_8));

                        ObjectMapper objectMapper = new ObjectMapper();
                        String jsonData = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
                        TKUtils.data = jsonData; // 同上，注意线程安全
                        tkUtil.data = jsonData;
                        // 处理JSON并添加到结果集合
                        error = handleJSON(selectResults, tkUtil);
                        // 已经找到了错误的场景
                        if (error == '1') {
                            break;
                        }
                    }

                    // 打印进度
                    num.incrementAndGet();
                    System.out.println("已处理" + num.get() + "/" + jsonFiles.size());

                } catch (Exception e) {
                    // 捕获单个文件处理的异常，包装后抛出
                    throw new RuntimeException("处理文件[" + file.getName() + "]失败", e);
                }
            });

        }// 关键步骤：等待所有任务完成
        executor.shutdown(); // 关闭线程池，不再接受新任务
        // 等待所有任务执行完毕（设置超时时间，根据实际处理时间调整）
        if (!executor.awaitTermination(24, TimeUnit.HOURS)) {
            executor.shutdownNow(); // 超时未完成则强制中断
            throw new Exception("处理超时，部分文件未完成");
        }
        // 处理完一个文件下的筛单，把当前结果存储到Excel
        RuleMesgJSON.exportToExcel(selectResults, FilePathMes.JX_PATH + "\\" + TKUtils.TK_Number + ".xlsx");
        selectResults.clear();
        System.out.println("所有文件处理完成，共" + jsonFiles.size() + "个文件");
    }

    public static Integer handleJSON(List<SelectResult> selectResults, TKUtil tkUtil) throws IOException, ClassNotFoundException, IllegalAccessException {
        // 打印一下当前需要处理的JSON
        /*System.out.println("===========================");
        System.out.println(TKUtils.data);
        File file = new File("D:\\11040162\\Desktop\\JSONData.txt");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(TKUtils.data.getBytes());
        System.out.println("===========================");*/
        // 将当前JSON转换成规则引擎需要识别的JSON
        JSONObject m1 = new JSONObject();
        if (FilePathMes.THREAD_NUM > 1) {
            m1 = new JSONObject(JSONObject.parseObject(tkUtil.data));
        } else {
            m1 = new JSONObject(JSONObject.parseObject(TKUtils.data));
        }
        JSONObject m2 = m1.getJSONObject("utScene");
        JSONObject m3 = m2.getJSONObject("utEntity");
        JSONObject m4 = m3.getJSONObject("child");
        // 应该将childer作为一个总结点传入
        JSONArray utEntity = new JSONArray();
        List<Node> nodes = new ArrayList<>();
        try {
            utEntity = m4.getJSONArray("utEntity");
        } catch (Exception e) {
            // 抛异常，证明不是JSON
            utEntity.add(m4.getJSONObject("utEntity"));
        }

        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(utEntity.toJSONString());

        SelectResult productRes = new SelectResult();
        productRes.setRes("0");
        if (FilePathMes.THREAD_NUM > 1) {
            productRes.setTk_Number(JXFileUtils.getRealFileName(tkUtil.getTK_Number(), "."));
        } else {
            productRes.setTk_Number(JXFileUtils.getRealFileName(FilePathMes.FILE_NAME, "."));
        }
        int error = 0;
        for (int i = 0; i < rootNode.size(); i++) {
            Product product = new Product();
            List<Node> nodeList = new ArrayList<>();
            List<Pm> pmList = new ArrayList<>();
            traverse(rootNode.get(i), rootNode.get(i), 1, product, nodeList, pmList);
            product.setNodes(nodeList);

            // 模块不符合直接跳过当前模块
//            if(TKUtils.model == null || TKUtils.model.equals("") || !TKUtils.model.contains(product.getCode())){
////                System.out.println("跳过！"+TKUtils.model+";当前模块:"+product.getCode());
//                continue;
//            }
            // 将对象转化为JSON对象 - 当前Product对象
//            String productJSON = JSON.toJSONString(product);
            // 将对象转化为JSON对象 - 当前Parent对象
            List<Node> parentNode = deepCopy(nodeList);
            Parent parent = new Parent();
            parent.setClazz("Ent");
            parent.setRoot(product.getUuid());
            parent.setTarget(product.getUuid());
            parent.setNodes(parentNode);
            List<UserInput> userInputData = getUserInputData(product);


            RuleMesgJSON ruleMesgJSON = new RuleMesgJSON();
            ruleMesgJSON.setParent(parent);
            ruleMesgJSON.setProduct(product);
            ruleMesgJSON.setUserInput(userInputData);
            TKUtils.data = JSON.toJSONString(ruleMesgJSON);
            String data = JSON.toJSONString(ruleMesgJSON);
            // 结果打包发送到规则平台
            String res = PostTest.sendPostRequest(data);
            // 处理结果
            JSONObject resJS = JSONObject.parseObject(res);
            if (!resJS.getString("status").equals("0")) {
                productRes.setRes("-1");
            } else {
                // 找到错误的提前退出
                productRes.setRes("0");
                error = 1;
                break;
            }

//            System.out.println(selectResults);
        }
        selectResults.add(productRes);

//        ObjectMapper objectMapper = new ObjectMapper();
//        System.out.println(objectMapper.writeValueAsString(nodes));
        return error;
    }


    public static List<UserInput> getUserInputData(Product product) {
        List<UserInput> userInputs = new ArrayList<>();
        if (TKUtils.TK_Number == "" || TKUtils.TK_Number == null) {
            TKUtils.TK_Number = "error";
        }
        userInputs.add(new UserInput("TK", TKUtils.TK_Number));
        userInputs.add(new UserInput("pid", product.getUuid()));
        userInputs.add(new UserInput("uuid", product.getUuid()));
        return userInputs;
    }


    /**
     * 递归遍历utEntity节点
     *
     * @param currentNode
     * @param parentCode
     * @param i
     * @param product
     * @param nodeList
     * @param pmList
     */
    private static void traverse(JsonNode currentNode, JsonNode parentCode, int i, Product product, List<Node> nodeList, List<Pm> pmList) {
        if (currentNode == null || currentNode.isNull()) {
            return; // 终止条件：节点为空
        }


        List<Pm> pmValue = getPM_VALUE(currentNode);
        List<Pm> pmParent = getPM_VALUE(parentCode);


        Node node = new Node();
        Node parentNode = new Node();
        // 1. 处理当前节点（打印信息，可替换为实际业务逻辑）Product实体类
        if (parentCode != null) {
            // 获取父级的pm
            // 设置Product的节点数据
            if (i == 1) {
                for (Pm pm : pmValue) {
                    // 设置父节点属性参数 - 主节点
                    if (pm.getKey().equals("NAME")) {
                        product.setName(pm.getText());
                    }
                    if (pm.getKey().equals("CODE")) {
                        product.setCode(pm.getText());
                    }
                    i = -1;
                    if (pm.getKey().equals("uuid")) {
                        product.setUuid(pm.getText());
                        node.setPid(pm.getText());
                        parentNode.setPid(pm.getText());

                    }
                }
            }
            // 写入节点父级
            for (Pm pm : pmParent) {
                if (pm.getKey().equals("uuid")) {
                    node.setPid(pm.getText());
                    parentNode.setPid(pm.getText());
                }
            }
            // 写入节点当前UUID和名字
            for (Pm pm : pmValue) {
                if (pm.getKey().equals("uuid")) {
                    node.setUuid(pm.getText());
                    parentNode.setUuid(pm.getText());
                }
                if (pm.getKey().equals("NAME")) {
                    node.setName(pm.getText());
                    parentNode.setName(pm.getText());
                }

            }
        }

        // 处理node节点,将属性值加入Node中
        node.setPm(pmValue);
        // 2. 获取当前节点的child
        JsonNode childNode = currentNode.get("child");
        if (childNode == null || childNode.isNull()) {
            return; // 终止条件：没有child，停止递归
        }
        nodeList.add(node);
        // 3. 从child中提取下一层utEntity（可能是对象或数组）
        JsonNode nextUtEntity = childNode.get("utEntity");
        if (nextUtEntity == null || nextUtEntity.isNull()) {
            return; // 终止条件：child中没有utEntity，停止递归
        }

        // 4. 处理下一层utEntity（区分对象和数组）
        if (nextUtEntity.isArray()) {
            // 若utEntity是数组，遍历每个元素
            for (JsonNode element : nextUtEntity) {
                traverse(element, currentNode, i, product, nodeList, pmList); // 递归处理数组元素，层级+1
            }
        } else if (nextUtEntity.isObject()) {
            // 若utEntity是对象，直接递归处理
            traverse(nextUtEntity, currentNode, i, product, nodeList, pmList);
        }

    }


    public static void getPM_Text(JsonNode PM_TEXT, Node node) {

        ObjectMapper mapper = new ObjectMapper();

        // 2. 将JsonNode转换为JSONObject
        try {
            JSONObject PM_TEXT_JS = convertJsonNodeToJsonObject(PM_TEXT, mapper);
            // 获取utValue
            JSONArray utValue = PM_TEXT_JS.getJSONArray("utValue");
            int index = 0;
            for (Object value : utValue) {
                JSONObject pm = (JSONObject) value;
                if (index < node.getPm().size())
                    node.getPm().get(index).setText(pm.getString("uVal"));
                index++;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 将JsonNode转换为JSONObject
     *
     * @param jsonNode 待转换的JsonNode
     * @param mapper   Jackson的ObjectMapper
     * @return 转换后的JSONObject
     * @throws Exception 转换过程中可能出现的异常
     */
    private static JSONObject convertJsonNodeToJsonObject(JsonNode jsonNode, ObjectMapper mapper) throws Exception {
        // 步骤1：将JsonNode转为JSON字符串
        String jsonString = mapper.writeValueAsString(jsonNode);

        // 步骤2：用JSONObject解析字符串
        return JSONObject.parseObject(jsonString);
    }

    public static List<Pm> getPM_VALUE(JsonNode PM_VALUE) {
        List<Pm> pmList = new ArrayList<>();
        // 获取utValue
        ObjectMapper mapper = new ObjectMapper();


        // 2. 将JsonNode转换为JSONObject
        try {
            JSONObject PM_VALUE_JS = convertJsonNodeToJsonObject(PM_VALUE, mapper);
            // 获取utValue
            JSONArray pm2 = PM_VALUE_JS.getJSONObject("_mapXData").getJSONObject("PM_VALUE").getJSONArray("utValue");
            JSONArray pm3 = PM_VALUE_JS.getJSONObject("_mapXData").getJSONObject("PM_TEXT").getJSONArray("utValue");

            for (int i = 0; i < pm2.size(); i++) {
                Pm p = new Pm();
                JSONObject pm = pm2.getJSONObject(i);
                p.setKey(pm.getString("name"));
                p.setValue(pm.getString("uVal"));
                for (int i1 = 0; i1 < pm3.size(); i1++) {
                    JSONObject p1 = pm3.getJSONObject(i1);
                    if (pm.getString("name").equals(p1.getString("name"))) {
                        p.setText(p1.getString("uVal"));
                        break;
                    }
                }
                pmList.add(p);
            }
            // UUID和NAME存在String字段中
            JSONArray j = PM_VALUE_JS.getJSONArray("string");
            for (Object o : j) {
                Pm p = new Pm();
                JSONObject temp = (JSONObject) o;
                if ("_szName".equals(temp.getString("name"))) {
                    p.setKey("NAME");
                    p.setValue(0);
                    p.setText(temp.getString("value"));
                    pmList.add(p);
                }

                if ("uuid".equals(temp.getString("name"))) {
                    p.setKey("uuid");
                    p.setValue(0);
                    p.setText(temp.getString("value"));
                    pmList.add(p);
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return pmList;
    }

    public static List<Node> deepCopy(List<Node> nodes) {
        List<Node> n = new ArrayList<>();
        for (Node node : nodes) {
            List<Pm> pm = new ArrayList<>();
            for (Pm pm1 : node.getPm()) {
                pm.add(pm1.deepCopy());
            }
            n.add(node.DeepCopy(node, pm));
        }
        return n;

    }
}

